package de.dhbw.karlsruhe.picsim.model.memory.impl;

import de.dhbw.karlsruhe.picsim.model.memory.FileAddress;
import de.dhbw.karlsruhe.picsim.util.Bits;
import de.dhbw.karlsruhe.picsim.util.impl.BitUtilities;
import de.dhbw.karlsruhe.picsim.util.impl.Lengths;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Created by IntelliJ IDEA.
 * User: goesen
 * Date: Apr 14, 2010
 * Time: 9:50:29 AM
 */
public final class FileAddressImpl implements FileAddress {
    private static final Log log = LogFactory.getLog(FileAddressImpl.class);
    private final Bits ourBits;


    public FileAddressImpl(final Bits bits) {
        if (bits.getLength() != Lengths.FILE_ADDRESS_LENGTH) {
            log.error("File Address Length must be " + Lengths.FILE_ADDRESS_LENGTH + "but is " + bits.getLength());
        }
        ourBits = BitUtilities.clone(bits);
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("de.dhbw.karlsruhe.picsim.model.memory.impl.FileAddressImpl");
        sb.append("{ourBits=").append(ourBits);
        sb.append('}');
        sb.append("{asInteger=").append(BitUtilities.fromLeastSignificantBitFirst(ourBits));
        sb.append('}');
        return sb.toString();
    }

    @Override
    public Bits getBits() {
        return ourBits;
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof FileAddress)) {
            return false;
        }

        final FileAddress that = (FileAddress) o;

        return ourBits.equals(that.getBits());

    }

    @Override
    public int hashCode() {
        return ourBits.hashCode();
    }

    public static FileAddress intConAddress() {
        return new FileAddressImpl(BitUtilities.asLeastSignificantBitFirst(11, Lengths.FILE_ADDRESS_LENGTH));
    }

    public static FileAddress indirectAddress() {
        return createUnSafe(0);
    }

    public static FileAddress timerAddress() {
        return createUnSafe(1);
    }

    public static FileAddress optionAddress() {
        return createUnSafe(0x81);
    }

    public static FileAddress fsrAddress() {
        return new FileAddressImpl(BitUtilities.asLeastSignificantBitFirst(4, Lengths.FILE_ADDRESS_LENGTH));
    }

    public static FileAddress createUnSafe(final int value) {
        return new FileAddressImpl(BitUtilities.asLeastSignificantBitFirst(value, Lengths.FILE_ADDRESS_LENGTH));
    }

    public static FileAddress programCounterLatch() {
        return new FileAddressImpl(BitUtilities.asLeastSignificantBitFirst(10, Lengths.FILE_ADDRESS_LENGTH));
    }

    public static FileAddress programCounterLowAddress() {
        return new FileAddressImpl(BitUtilities.asLeastSignificantBitFirst(2, Lengths.FILE_ADDRESS_LENGTH));
    }


    public static FileAddress statusAddress() {
        return createUnSafe(3);
    }
}
